library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

ENTITY alu32bit IS
	port(a, b 						: IN std_logic_vector(31 downto 0);	-- a and b are busses
		operation 					: IN std_logic_vector(4 downto 0);
		CLK							: IN std_logic;
		z	 						: OUT std_logic;
	    f 							: OUT std_logic_vector(31 downto 0));
END alu32bit;

architecture alu_instance of alu32bit is
Signal cin, cout					: std_logic:= '0';
begin
process(a, b, operation, cin)
   Variable temp 		: std_logic_vector(32 downto 0);
	begin
    	temp := "000000000000000000000000000000000";
		case operation is
			when "00000" =>
				temp := ("0" & a) + b; --add
				cout <= temp(32);
			when "00001" =>
				temp := ("0" & a) + b + cin; --adc
				cout <= temp(32);
			when "00010" =>
				temp := ("0" & a) - b; --sub
				cout <= temp(32);
			when "00011" =>
				temp := ("0" & a) + 1; --inc
				cout <= temp(32);
			when "00100" =>	
			   temp := ("0" & a) - 1; --dec
			   cout <= temp(32);
			when "00101" =>
				temp(31 downto 0) := a and b;  --and
				cout <= '0';
			when "00110" =>
			   temp(31 downto 0) := a xor b;  --xor
				cout <= '0';
			when "00111" =>
				temp(31 downto 0) := a or b;  --or
				cout <= '0';
			when "01000" =>
				temp(31 downto 0) := not a;  --not
				cout <= '0';
			when "01001" =>
				temp := ("0" & a) - b; --cmp
				cout <= temp(32);
			when "01010" => --clr
				temp := "000000000000000000000000000000000";
			when "01011" =>
				temp(0) := '0'; --shl
				temp(31 downto 1) := a(30 downto 0);
				cout <= a(31);
			when "01100" =>
				temp(31) := '0'; --shr
				temp(30 downto 0) := a(31 downto 1);
				cout <= a(0);
			when "01101" =>
				temp(31) := a(0); --ror
				temp(30 downto 0) := a(31 downto 1);
				cout <= a(0);
			when "01110" =>
				temp(31) := cin; -- rorc
				temp(30 downto 0) := a(31 downto 1);
				cout <= a(0);
			when "01111" =>
				temp(0) := a(31); --rol
				temp(31 downto 1) := a(30 downto 0);
				cout <= a(31);
			when "10000" =>
				temp(0) := cin; -- rolc
				temp(31 downto 1) := a(30 downto 0);
				cout <= a(31);
			when "10001" => --clc
				cout <= '0';
				temp(31 downto 0) := a;
			when "10010" => --stc
				cout <= '1';
				temp(31 downto 0) := a;
			when others => 
				temp(31 downto 0) := a;
		end case;
		if (temp(31 downto 0) = "00000000000000000000000000000000"  and operation /= "10011") then -- clz
	   		z <= '1';
		else
	   		z <= '0';
		end if;
		f <= temp(31 downto 0);
end process;
process (CLK, cout)
	Begin
	if falling_edge(CLK) then
		cin <= cout;
	end if;
end process;
end alu_instance;
